将字段首字母改为小写或添加 json:"-"
标签能够在 json.Marshal()
时忽略指定字段,但此文章想讨论的是在不修改原 struct 结构的前提下过忽略部分字段的方法。
为什么会有这种需求呢?如果要转为 json 的 struct 定义在依赖包中或有其他地方需要输出这些字段,这时就不能修改原 struct。
定义只有必要字段的新 struct
定义新 struct,在新 struct 中只保留必要字段。
1 | type source struct { |
这是最容易想到的方法,但当字段较多或 struct 较复杂(比如嵌套多层其他 struct)时就会有很多将 source
的字段赋值给 target
的操作。
定义 tag 不同结构相同的 struct
此方法仅适用 golang 1.8+,1.8 之后结构相同但 tag 不同的 struct 之间能够强制转换。利用这个特性,我们能简化掉字段赋值的操作。完整示例点击这里。
1 | type source struct { |
通过 map 转换
json 和 struct 转换时,struct 必须提前定义好。如果不知道结构或不想定义 struct,可以将其转为 interface{}
1 | func main() { |
上面的执行结果是 map[test:abc]
。
所以可以将原 struct 转为 map[string]interface{}
,将需要的字段保存入新的 map[string]interface{}
,然后转为 json:
1 | type obj map[string]interface{} |
trim()
的 source
参数是原始 struct,target
参数中只保留需要的字段。原始 struct 和 target
示例:
1 | type T1 struct { |
trim()
的返回值是只保留需要字段的 map[string]interface{}
,再将其 json.Marshal()
即可
1 | out := trim(source, target) |
完整代码请看 gist 或 play (只是 demo,没经过大量测试)。使用这种方法只需要定义出 target
,不需要像上两个方法那样重新定义 struct,代码会更简洁一些。